package no.ntnu.fp.su.wellsim.sensors;

import no.ntnu.fp.su.wellsim.Flow;
import no.ntnu.fp.su.wellsim.util.NormalDistribution;

/**
 * An erosion probe. The erosion material values are from Monel 400, as used in
 * at least 1 actual product [0].
 * 
 * The resistivity of Monel 400 at 21 degrees celsius is 5.11*10^-4 ohm-meters
 * [3].
 * 
 * The temperature coefficient of resistance [1] of Monel 400 is assumed to be
 * 0.63*alhpa_nickel + 0.34*alpha_copper + 0.03*alpha_iron, a naive
 * approximation based on Monel 400's composition, since no exact value could be
 * found.
 * 
 * [0] http://www.roxar.com/getfile.php/Files/Product%20Datasheets/Topside/
 * DataSheet_SandErosionProbe_VerA_LoRes.pdf [1]
 * http://www.allaboutcircuits.com/vol_1/chpt_12/6.html [2] Y. Zhang, E.P.
 * Reuterfors, B.S. McLaury, S.A. Shirazi, E.F. Rybicki, Comparison of computed
 * and measured particle velocities and erosion in water and air flows, Wear,
 * Volume 263, Issues 1-6, 16th International Conference on Wear of Materials,
 * 10 September 2007, Pages 330-338, ISSN 0043-1648, DOI:
 * 10.1016/j.wear.2006.12.048.
 * (http://www.sciencedirect.com/science/article/B6V5B
 * -4NT57HS-29/2/b886a9ce1a48da5f7886b2a2f1676069) [3]
 * www.specialmetals.com/documents/Monel%20alloy%20400.pdf
 */
public class ErosionProbe implements Sensor {
	private static double resistivity = 0.000511; // ohm-meters
	private static double temperatureCoefficent = 0.00523965; // alpha/C
	private static double referenceTemperature = 21.0; // C
	private double area = 0.046; // meters^2
	private double temperature; // C
	private double distance = 0.3; // meters
	private Flow flow;
	private double metersFromReservoir;

	public ErosionProbe(Flow flow, double metersFromReservoir) {
		this.flow = flow;
		this.metersFromReservoir = metersFromReservoir;
	}

	@Override
	public double sample() {
		temperature = flow.getTemperature(metersFromReservoir);
		double er = getErosionRatio(165, .53, flow.getVelocity(), 0);
		area -= area * er * flow.getSandContent(); // not physically correct
		return NormalDistribution.sample(
				resistivity
						* (distance / area)
						* (temperatureCoefficent
								* (temperature - referenceTemperature) + 1.0),
				0.00000005);
	}

	/**
	 * Erosion model from [2] pp6.
	 * 
	 * @param brinellHardness
	 *            For Monel 400, a reasonable assumption would be 165 [3], pp2.
	 * @param particleShapeCoefficient
	 *            Fs = 1.0 for sharp (angular), 0.53 for semi-rounded, or 0.2
	 *            for fully rounded sand particles. [2]
	 * @param particleImpactSpeed
	 *            particle impact speed in m/s.
	 * @param theta
	 *            The impact angle in radians.
	 * 
	 * @return Erosion ratio, defined as the amount of mass lost by the wall
	 *         material due to particle impacts divided by the mass of particles
	 *         impacting.
	 */
	private double getErosionRatio(double brinellHardness,
			double particleShapeCoefficient, double particleImpactSpeed,
			double theta) {
		double n = 2.41;
		double C = 2.17 * Math.pow(10, -7);
		double fTheta = 0;
		double[] a = { 5.40, -10.11, 10.93, -6.33, 1.42 };
		for (int i = 0; i < 5; i++) {
			fTheta += a[i] * Math.pow(theta, i);
		}
		return C * Math.pow(brinellHardness, -.59) * particleShapeCoefficient
				* Math.pow(particleImpactSpeed, n) * fTheta;
	}

}
